home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 15 / CU Amiga Magazine's Super CD-ROM 15 (1997)(EMAP Images)(GB)[!][issue 1997-10].iso / CUCD / Graphics / Ghostscript / source / gdevxes.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-14  |  6.5 KB  |  220 lines

  1. /* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.  All rights reserved.
  2.  
  3. This file is part of Ghostscript.
  4.  
  5. Ghostscript is distributed in the hope that it will be useful, but
  6. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  7. to anyone for the consequences of using it or for whether it serves any
  8. particular purpose or works at all, unless he says so in writing.  Refer
  9. to the Ghostscript General Public License for full details.
  10.  
  11. Everyone is granted permission to copy, modify and redistribute
  12. Ghostscript, but only under the conditions described in the Ghostscript
  13. General Public License.  A copy of this license is supposed to have been
  14. given to you along with Ghostscript so you can know your rights and
  15. responsibilities.  It should be in a file named COPYLEFT.  Among other
  16. things, the copyright notice and this notice must be preserved on all
  17. copies.  */
  18.  
  19. /*
  20. gdevxes.c
  21. Ghostscript driver for Xerox XES printer
  22.   (2700, 3700, 4045, etc.)
  23.  
  24. Peter Flass - NYS LBDC <flass@lbdrscs.bitnet>
  25. New York State Legislative Bill Drafting Commission
  26. 1450 Western Avenue, 3rd floor
  27. Albany, NY  12203
  28.  
  29. This code is subject to the GNU General Public License
  30.  
  31. Operation: The page bitmap is scanned to determined the
  32. actual margins.  A "graphics rectangle" is defined to
  33. contain the included data and positioned on the page.
  34. The bitmap is then re-read and "sixellized" by converting
  35. each three bytes to four six-bit chunks (zero padding on
  36. the right if necessary) and adding x'3F' to generate a
  37. printable code.  Runs of up to 32767 identical characters
  38. are compressed to an ascii count and a single character.
  39.  
  40. */
  41.  
  42. #include "gdevprn.h"
  43.  
  44. /* Forward references */
  45. private int sixel_print_page(P3(gx_device_printer *pdev,
  46.                    FILE *prn_stream, const char *init));
  47.  
  48. /* The device descriptor */
  49. private dev_proc_output_page(sixel_output_page);
  50. private dev_proc_print_page(xes_print_page);
  51. private gx_device_procs xes_procs =
  52.   prn_procs(gdev_prn_open, sixel_output_page, gdev_prn_close);
  53.  
  54. #ifdef A4
  55. #  define BOTTOM_MARGIN 0.5
  56. #  define PAGE_LENGTH_PELS 3300
  57. #else
  58. #  define BOTTOM_MARGIN 0.4
  59. #  define PAGE_LENGTH_PELS 3300
  60. #endif
  61.  
  62. gx_device_printer gs_xes_device =
  63.     prn_device(xes_procs, "xes",
  64.            DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
  65.            300, 300,        /* x_dpi, y_dpi */
  66.            0, BOTTOM_MARGIN, 0, 0,    /* left, bottom, right, top margin */
  67.            1, xes_print_page);
  68.  
  69. /*
  70.  * Initialization string: switch to graphics mode, 300 dpi
  71.  * <ESC>+X        Reset    soft terminal reset
  72.  * <ESC>gw1;0,0,        Graphic window
  73.  */
  74.  
  75. #define XES_RESET \
  76.  "\033+X\n"
  77. #define XES_GRAPHICS \
  78.  "\033gw1;"
  79.  
  80. private int
  81. xes_print_page(gx_device_printer *pdev, FILE *prn_stream)
  82. {
  83.     return (sixel_print_page(pdev,prn_stream,XES_RESET));
  84. }
  85.  
  86. /* ------ Internal routines ------ */
  87.  
  88. /* Open the printer in text mode before gdev_prn_output_page */
  89. /* opens it in binary mode. */
  90. private int
  91. sixel_output_page(gx_device *pdev, int num_copies, int flush)
  92. {    int code = gdev_prn_open_printer(pdev, 0);
  93.     if ( code < 0 )
  94.         return code;
  95.     return gdev_prn_output_page(pdev, num_copies, flush);
  96. }
  97.  
  98. /* Send the page to the printer. */
  99. private int
  100. sixel_print_page(gx_device_printer *pdev, FILE *prn_stream, const char *init)
  101. {
  102.     byte *buf, *b, *end;
  103.     byte last = '\0';
  104.     byte tmp[4];
  105.     char run[8], *t;
  106.     int lnum, l, line_size;
  107.     int width, height;
  108.     int top, bottom, left, right;
  109.     int count = 0;
  110.  
  111.     line_size = gdev_mem_bytes_per_scan_line(pdev);
  112.     height = pdev->height; 
  113.     /* Default page rectangle */
  114.     top    = pdev->height;
  115.     left   = line_size;
  116.     right  = 0;
  117.     bottom = 0;
  118.  
  119.     buf = (byte *)gs_malloc(line_size, 1, "sixel_print_page");
  120.     end = buf + line_size - 1;
  121.  
  122.     /* Check allocation */
  123.     if (!buf) 
  124.       return_error(gs_error_VMerror);
  125.  
  126.     /* Compute required window size */
  127.     for (lnum=0; lnum < pdev->height; lnum++ ) {
  128.     gdev_prn_copy_scan_lines(pdev, lnum, buf, line_size);
  129.     for( b=buf; b<=end; b++ ) if(*b) break;
  130.     if ( b<=end ) {
  131.       top  = min( top, lnum );
  132.       left = min( left, (int)(b-buf));
  133.       bottom = max( bottom, lnum );
  134.       for( b=end; b>=buf; b-- ) if(*b) break;
  135.       if ( b>=buf ) right = max( right, (int)(b-buf) );
  136.       } /* endif */
  137.     } /* endfor */
  138.     width = right - left + 1;    /* width in bytes */
  139.     height= bottom- top  + 1;    /* height in pels */
  140.     /* round width to multiple of 3 bytes */
  141.     width = ( (width+2) / 3 ) * 3;
  142.     right = min( line_size-1, left+width-1 );
  143.     end = buf + right;        /* recompute EOL  */
  144.  
  145.     fputs( init, prn_stream );
  146.  
  147.     /* Position and size graphics window */
  148.     fprintf( prn_stream, "%s%d,%d,%d,%d\n", 
  149.              XES_GRAPHICS, 
  150.              left*8, PAGE_LENGTH_PELS-top, 
  151.              width*8, height );
  152.  
  153.     /* Print lines of graphics                 */
  154.     for (lnum = top; lnum <= bottom; lnum++ ) {
  155.     gdev_prn_copy_scan_lines(pdev, lnum, buf, line_size);
  156.     for ( b=buf+left; b<=end ; ) {
  157.       /* grab data in 3-byte chunks   */
  158.       /* with zero pad at end-of-line */
  159.       tmp[0]=tmp[1]=tmp[2]='\0';
  160.       tmp[0]=*b++;
  161.       if (b<=end) tmp[1]=*b++;
  162.       if (b<=end) tmp[2]=*b++;
  163.       /* sixellize data */
  164.       tmp[3] = ( tmp[2] & 0x3F) + 0x3F;
  165.       tmp[2] = ( tmp[2] >> 6 |
  166.                 (tmp[1] & 0x0F) << 2 ) + 0x3F;
  167.       tmp[1] = ( tmp[1] >> 4 |
  168.                 (tmp[0] & 0x03) << 4 ) + 0x3F;
  169.       tmp[0] = ( tmp[0] >> 2 ) + 0x3F;
  170.       /* build runs of identical characters */
  171.       /* longest run length is 32767 bytes  */
  172.       for ( l=0; l<4; l++) {
  173.           if ( tmp[l] == last ) {
  174.         count++;
  175.         if (count==32767) {
  176.           run[sprintf(run, "%d", count)]='\0';
  177.           for (t=run; *t; t++)fputc( *t, prn_stream ); 
  178.           fputc( last, prn_stream ); 
  179.           last = '\0';
  180.           count = 0;
  181.           } /* end if count */
  182.         } /* end if tmp[l] */
  183.           else {
  184.           /* emit single character or run */
  185.           switch (count) {
  186.             case 0: break;
  187.             case 1: fputc( last, prn_stream );
  188.                 break;
  189.             default:run[sprintf(run, "%d", count)]='\0';
  190.                 for (t=run; *t; t++) fputc( *t, prn_stream );
  191.                 fputc( last, prn_stream );
  192.                 break;
  193.             } /* end switch */
  194.           last = tmp[l];
  195.           count = 1;
  196.           } /* end else */
  197.       } /* end for l */
  198.     } /* end for b */
  199.     } /* end for lnum */
  200.  
  201.     /* Write final run */
  202.     switch (count) {
  203.       case 0: break;
  204.       case 1: fputc( last, prn_stream );
  205.           break;
  206.       default:run[sprintf(run, "%d", count)]='\0';
  207.           for (t=run; *t; t++) fputc( *t, prn_stream );
  208.           fputc( last, prn_stream );
  209.           break;
  210.       } /* end switch */
  211.  
  212.     /* Eject page and reset */
  213.     fprintf( prn_stream, "\f%s", XES_RESET );
  214.     fflush(prn_stream);
  215.  
  216.     gs_free((char *)buf, line_size, 1, "sixel_print_page");
  217.  
  218.     return(0);
  219. }
  220.